home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / devs / nil_handler.c < prev    next >
C/C++ Source or Header  |  1996-09-12  |  7KB  |  318 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: nil_handler.c,v 1.2 1996/09/12 14:52:00 digulla Exp $
  4.     $Log: nil_handler.c,v $
  5.     Revision 1.2  1996/09/12 14:52:00  digulla
  6.     Use correct way to access external names (was missing)
  7.  
  8.     Revision 1.1  1996/09/11 12:52:54  digulla
  9.     Two new devices by M. Fleischer: RAM: and NIL:
  10.  
  11.     Desc:
  12.     Lang:
  13. */
  14. #include <exec/resident.h>
  15. #include <exec/memory.h>
  16. #include <clib/exec_protos.h>
  17. #include <utility/tagitem.h>
  18. #include <dos/dosextens.h>
  19. #include <dos/filesystem.h>
  20. #include <clib/dos_protos.h>
  21. #include <aros/libcall.h>
  22. #ifdef __GNUC__
  23.     #include "nil_handler_gcc.h"
  24. #endif
  25.  
  26. static const char name[];
  27. static const char version[];
  28. static const APTR inittabl[4];
  29. static void *const functable[];
  30. struct nilbase *__AROS_SLIB_ENTRY(init,nil_handler)();
  31. void __AROS_SLIB_ENTRY(open,nil_handler)();
  32. BPTR __AROS_SLIB_ENTRY(close,nil_handler)();
  33. BPTR __AROS_SLIB_ENTRY(expunge,nil_handler)();
  34. int __AROS_SLIB_ENTRY(null,nil_handler)();
  35. void __AROS_SLIB_ENTRY(beginio,nil_handler)();
  36. LONG __AROS_SLIB_ENTRY(abortio,nil_handler)();
  37. static const char end;
  38.  
  39. struct device
  40. {
  41.     struct DosList *doslist;
  42.     ULONG usecount;
  43. };
  44.  
  45. int nil_handler_entry(void)
  46. {
  47.     /* If the handler was executed by accident return error code. */
  48.     return -1;
  49. }
  50.  
  51. const struct Resident nil_handler_resident=
  52. {
  53.     RTC_MATCHWORD,
  54.     (struct Resident *)&nil_handler_resident,
  55.     (APTR)&end,
  56.     RTF_AUTOINIT,
  57.     1,
  58.     NT_DEVICE,
  59.     0,
  60.     (char *)name,
  61.     (char *)&version[6],
  62.     (ULONG *)inittabl
  63. };
  64.  
  65. static const char name[]="nil.handler";
  66.  
  67. static const char version[]="$VER: nil_handler 1.0 (8.6.96)\n\015";
  68.  
  69. static const APTR inittabl[4]=
  70. {
  71.     (APTR)sizeof(struct nilbase),
  72.     (APTR)functable,
  73.     NULL,
  74.     &__AROS_SLIB_ENTRY(init,nil_handler)
  75. };
  76.  
  77. static void *const functable[]=
  78. {
  79.     &__AROS_SLIB_ENTRY(open,nil_handler),
  80.     &__AROS_SLIB_ENTRY(close,nil_handler),
  81.     &__AROS_SLIB_ENTRY(expunge,nil_handler),
  82.     &__AROS_SLIB_ENTRY(null,nil_handler),
  83.     &__AROS_SLIB_ENTRY(beginio,nil_handler),
  84.     &__AROS_SLIB_ENTRY(abortio,nil_handler),
  85.     (void *)-1
  86. };
  87.  
  88. __AROS_LH2(struct nilbase *, init,
  89.  __AROS_LHA(struct nilbase *, nilbase, D0),
  90.  __AROS_LHA(BPTR,             segList, A0),
  91.        struct ExecBase *, sysBase, 0, nil_handler)
  92. {
  93.     __AROS_FUNC_INIT
  94.  
  95.     /* Store arguments */
  96.     nilbase->sysbase=sysBase;
  97.     nilbase->seglist=segList;
  98.     nilbase->dosbase=(struct DosLibrary *)OpenLibrary("dos.library",39);
  99.     if(nilbase->dosbase!=NULL)
  100.     return nilbase;
  101.  
  102.     return NULL;
  103.     __AROS_FUNC_EXIT
  104. }
  105.  
  106. __AROS_LH3(void, open,
  107.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  108.  __AROS_LHA(ULONG,              unitnum, D0),
  109.  __AROS_LHA(ULONG,              flags, D0),
  110.        struct nilbase *, nilbase, 1, nil_handler)
  111. {
  112.     __AROS_FUNC_INIT
  113.  
  114.     /* Keep compiler happy */
  115.     unitnum=0;
  116.     flags=0;
  117.  
  118.     /* I have one more opener. */
  119.     nilbase->device.dd_Library.lib_OpenCnt++;
  120.     nilbase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  121.  
  122.     /* Set returncode */
  123.     iofs->IOFS.io_Error=0;
  124.  
  125.     /* Mark Message as recently used. */
  126.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  127.     __AROS_FUNC_EXIT
  128. }
  129.  
  130. __AROS_LH1(BPTR, close,
  131.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  132.        struct nilbase *, nilbase, 2, nil_handler)
  133. {
  134.     __AROS_FUNC_INIT
  135.  
  136.     /* Let any following attemps to use the device crash hard. */
  137.     iofs->IOFS.io_Device=(struct Device *)-1;
  138.  
  139.     /* I have one fewer opener. */
  140.     if(!--nilbase->device.dd_Library.lib_OpenCnt)
  141.     {
  142.     /* Delayed expunge pending? */
  143.     if(nilbase->device.dd_Library.lib_Flags&LIBF_DELEXP)
  144.         /* Then expunge the device */
  145.         return expunge();
  146.     }
  147.     return 0;
  148.     __AROS_FUNC_EXIT
  149. }
  150.  
  151. __AROS_LH0(BPTR, expunge, struct nilbase *, nilbase, 3, nil_handler)
  152. {
  153.     __AROS_FUNC_INIT
  154.  
  155.     BPTR ret;
  156.     /*
  157.     This function is single-threaded by exec by calling Forbid.
  158.     Never break the Forbid() or strange things might happen.
  159.     */
  160.  
  161.     /* Test for openers. */
  162.     if(nilbase->device.dd_Library.lib_OpenCnt)
  163.     {
  164.     /* Set the delayed expunge flag and return. */
  165.     nilbase->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  166.     return 0;
  167.     }
  168.  
  169.     /* Free all resources */
  170.     CloseLibrary((struct Library *)nilbase->dosbase);
  171.  
  172.     /* Get rid of the device. Remove it from the list. */
  173.     Remove(&nilbase->device.dd_Library.lib_Node);
  174.  
  175.     /* Get returncode here - FreeMem() will destroy the field. */
  176.     ret=nilbase->seglist;
  177.  
  178.     /* Free the memory. */
  179.     FreeMem((char *)nilbase-nilbase->device.dd_Library.lib_NegSize,
  180.         nilbase->device.dd_Library.lib_NegSize+nilbase->device.dd_Library.lib_PosSize);
  181.  
  182.     return ret;
  183.     __AROS_FUNC_EXIT
  184. }
  185.  
  186. __AROS_LH0I(int, null, struct nilbase *, nilbase, 4, nil_handler)
  187. {
  188.     __AROS_FUNC_INIT
  189.     return 0;
  190.     __AROS_FUNC_EXIT
  191. }
  192.  
  193. __AROS_LH1(void, beginio,
  194.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  195.        struct nilbase *, nilbase, 5, nil_handler)
  196. {
  197.     __AROS_FUNC_INIT
  198.     LONG error=0;
  199.     struct device *dev;
  200.     struct DosList *dl;
  201.  
  202.     /*
  203.     Do everything quick no matter what. This is possible
  204.     because I never need to Wait().
  205.     */
  206.     switch(iofs->IOFS.io_Command)
  207.     {
  208.     case FSA_MOUNT:
  209.         /* AddDosEntry() may Wait(), so return error code if necessary */
  210.         if(!(iofs->IOFS.io_Flags&IOF_QUICK))
  211.         {
  212.         error=ERROR_NOT_IMPLEMENTED;
  213.         break;
  214.         }
  215.         dev=AllocMem(sizeof(struct device),MEMF_PUBLIC|MEMF_CLEAR);
  216.         if(dev!=NULL)
  217.         {
  218.         dl=MakeDosEntry((STRPTR)iofs->io_Args[0],DLT_DEVICE);
  219.         if(dl!=NULL)
  220.         {
  221.             dl->dol_Unit=(struct Unit *)dev;
  222.             dl->dol_Device=&nilbase->device;
  223.             dev->doslist=dl;
  224.             if(AddDosEntry(dl))
  225.             break;
  226.             else
  227.             error=ERROR_OBJECT_EXISTS;
  228.             FreeDosEntry(dl);
  229.         }else
  230.             error=ERROR_NO_FREE_STORE;
  231.         FreeMem(dev,sizeof(struct device));
  232.         }
  233.         else
  234.         error=ERROR_NO_FREE_STORE;
  235.         break;
  236.  
  237.     case FSA_DISMOUNT:
  238.         /* RemDosEntry() may wait, so return error code if necessary */
  239.         if(!(iofs->IOFS.io_Flags&IOF_QUICK))
  240.         {
  241.         error=ERROR_NOT_IMPLEMENTED;
  242.         break;
  243.         }
  244.         LockDosList(LDF_DEVICES|LDF_WRITE);
  245.         dev=(struct device *)iofs->IOFS.io_Unit;
  246.         if(dev->usecount==1)
  247.         {
  248.         RemDosEntry(dev->doslist);
  249.         FreeDosEntry(dev->doslist);
  250.         FreeMem(dev,sizeof(struct device));
  251.         }else
  252.         {
  253.         Forbid();
  254.         dev->usecount--;
  255.         Permit();
  256.         error=ERROR_OBJECT_IN_USE;
  257.         }
  258.         UnLockDosList(LDF_DEVICES|LDF_WRITE);
  259.         break;
  260.  
  261.     case FSA_OPEN:
  262.     case FSA_OPEN_FILE:
  263.         /* No names allowed on NIL: */
  264.         if(((STRPTR)iofs->io_Args[0])[0])
  265.         {
  266.         error=ERROR_OBJECT_NOT_FOUND;
  267.         break;
  268.         }
  269.         Forbid();
  270.         ((struct device *)iofs->IOFS.io_Unit)->usecount++;
  271.         Permit();
  272.         break;
  273.  
  274.     case FSA_READ:
  275.         iofs->io_Args[1]=0;
  276.         break;
  277.  
  278.     case FSA_WRITE:
  279.         break;
  280.  
  281.     case FSA_SEEK:
  282.         iofs->io_Args[0]=0;
  283.         iofs->io_Args[1]=0;
  284.         break;
  285.  
  286.     case FSA_CLOSE:
  287.         Forbid();
  288.         ((struct device *)iofs->IOFS.io_Unit)->usecount--;
  289.         Permit();
  290.         break;
  291.  
  292.     default:
  293.         error=ERROR_NOT_IMPLEMENTED;
  294.         break;
  295.     }
  296.  
  297.     /* Set error code */
  298.     iofs->io_DosError=error;
  299.  
  300.     /* If the quick bit is not set send the message to the port */
  301.     if(!(iofs->IOFS.io_Flags&IOF_QUICK))
  302.     ReplyMsg(&iofs->IOFS.io_Message);
  303.  
  304.     __AROS_FUNC_EXIT
  305. }
  306.  
  307. __AROS_LH1(LONG, abortio,
  308.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  309.        struct nilbase *, nilbase, 6, nil_handler)
  310. {
  311.     __AROS_FUNC_INIT
  312.     /* Everything already done. */
  313.     return 0;
  314.     __AROS_FUNC_EXIT
  315. }
  316.  
  317. static const char end=0;
  318.